#include "GY_TransformGroup.h"
#include <QDebug>
#include <math.h>

GY_TransformGroup::GY_TransformGroup(const QString &guid, QGraphicsItem *parent)
    : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    updateDraw();
    this->setCenterPointF(m_PropertyInfoMap["Position"].propertyValue.toPointF());
}

void GY_TransformGroup::setContainerEditPointF()
{
    //四个点因画板垂直翻转
    m_Width = this->boundingRect().width();
    m_height = this->boundingRect().height();
    this->setEditPointF("LeftTop",QPointF(this->childrenBoundingRect().x(),this->childrenBoundingRect().y()));
    this->setEditPointF("RightTop",QPointF(this->childrenBoundingRect().x()+this->childrenBoundingRect().width()
                                     ,this->childrenBoundingRect().y()));
    this->setEditPointF("LeftBottom",QPointF(this->childrenBoundingRect().x()
                                       ,this->childrenBoundingRect().y()+this->childrenBoundingRect().height()));
    this->setEditPointF("RightBottom",QPointF(this->childrenBoundingRect().x() + this->childrenBoundingRect().width()
                                          ,this->childrenBoundingRect().y() + this->childrenBoundingRect().height()));
    this->setEditPointF("RotationPoint",QPointF(this->childrenBoundingRect().x()+this->childrenBoundingRect().width()/2
                                            ,this->childrenBoundingRect().y()+this->childrenBoundingRect().height()/2));
    m_PropertyInfoMap["LeftTop"].propertyValue = QPointF(this->childrenBoundingRect().x(),this->childrenBoundingRect().y());
    m_PropertyInfoMap["RightTop"].propertyValue = QPointF(this->childrenBoundingRect().x()+this->childrenBoundingRect().width()
                                                          ,this->childrenBoundingRect().y());
    m_PropertyInfoMap["LeftBottom"].propertyValue = QPointF(this->childrenBoundingRect().x()
                                                            ,this->childrenBoundingRect().y()+this->childrenBoundingRect().height());
    m_PropertyInfoMap["RightBottom"].propertyValue = QPointF(this->childrenBoundingRect().x() + this->childrenBoundingRect().width()
                                                             ,this->childrenBoundingRect().y() + this->childrenBoundingRect().height());
    m_PropertyInfoMap["RotationPoint"].propertyValue = QPointF(this->childrenBoundingRect().x()+this->childrenBoundingRect().width()/2
                                                               ,this->childrenBoundingRect().y()+this->childrenBoundingRect().height()/2);
}

void GY_TransformGroup::computationScaling()
{
    qreal width = m_PropertyInfoMap["RightBottom"].propertyValue.toPointF().x()-m_PropertyInfoMap["LeftBottom"].propertyValue.toPointF().x();
    qreal height = -m_PropertyInfoMap["RightTop"].propertyValue.toPointF().y()+m_PropertyInfoMap["RightBottom"].propertyValue.toPointF().y();
    QPointF scaling = m_PropertyInfoMap["Scaling"].propertyValue.toPointF();
    scaling.setX(width/m_Width);
    scaling.setY(height/m_height);
    m_PropertyInfoMap["Scaling"].propertyValue = scaling;
}

void GY_TransformGroup::initializationPropertyInfo()
{
    //隐藏
    GY_PropertyInfo isVisiblePropertyInfo(this);
    isVisiblePropertyInfo.propertyName="IsVisible";
    isVisiblePropertyInfo.propertyValue=true;
    isVisiblePropertyInfo.updateType = Update|OrdinaryAttributes;
    isVisiblePropertyInfo.propertyType = BoolPropertyType;
    isVisiblePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateIsVisible;
    m_PropertyInfoMap.insert(isVisiblePropertyInfo.propertyName,isVisiblePropertyInfo);
    m_PropertyInfoMap[isVisiblePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    //旋转角度
    GY_PropertyInfo rotationPropertyInfo(this);
    rotationPropertyInfo.propertyName="Rotation";
    rotationPropertyInfo.propertyValue=0;
    rotationPropertyInfo.updateType = Update|OrdinaryAttributes;
    rotationPropertyInfo.propertyType = QrealPropertyType;
    rotationPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateRotation;
    m_PropertyInfoMap.insert(rotationPropertyInfo.propertyName,rotationPropertyInfo);
    m_PropertyInfoMap[rotationPropertyInfo.propertyName].setConnect();

    //缩放比
    GY_PropertyInfo scalingYPropertyInfo(this);
    scalingYPropertyInfo.propertyName="Scaling";
    scalingYPropertyInfo.propertyValue=QPointF(1,1);
    scalingYPropertyInfo.updateType = Update|OrdinaryAttributes;
    scalingYPropertyInfo.propertyType = PointPropertyType;
    scalingYPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateScaling;
    m_PropertyInfoMap.insert(scalingYPropertyInfo.propertyName,scalingYPropertyInfo);
    m_PropertyInfoMap[scalingYPropertyInfo.propertyName].setConnect();

    //是否允许旋转
    GY_PropertyInfo rotationInEditModePropertyInfo(this);
    rotationInEditModePropertyInfo.propertyName="RotationInEditMode";
    rotationInEditModePropertyInfo.propertyValue=true;
    rotationInEditModePropertyInfo.updateType = Update|OrdinaryAttributes;
    rotationInEditModePropertyInfo.propertyType = BoolPropertyType;
    rotationInEditModePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateRotationInEditMode;
    m_PropertyInfoMap.insert(rotationInEditModePropertyInfo.propertyName,rotationInEditModePropertyInfo);
    m_PropertyInfoMap[rotationInEditModePropertyInfo.propertyName].setConnect();

    //是否允许缩放
    GY_PropertyInfo scaleInEditModePropertyInfo(this);
    scaleInEditModePropertyInfo.propertyName="ScaleInEditMode";
    scaleInEditModePropertyInfo.propertyValue=true;
    scaleInEditModePropertyInfo.updateType = Update|OrdinaryAttributes;
    scaleInEditModePropertyInfo.propertyType = BoolPropertyType;
    scaleInEditModePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateScaleInEditMode;
    m_PropertyInfoMap.insert(scaleInEditModePropertyInfo.propertyName,scaleInEditModePropertyInfo);
    m_PropertyInfoMap[scaleInEditModePropertyInfo.propertyName].setConnect();

    //拖动点
    GY_PropertyInfo leftTop(this);
    leftTop.propertyName="LeftTop";
    leftTop.propertyValue=QPointF(this->boundingRect().x(),this->boundingRect().y());
    leftTop.updateType = NotUpdate;
    leftTop.propertyType = PointPropertyType;
    leftTop.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateLeftTop;
    m_PropertyInfoMap.insert(leftTop.propertyName,leftTop);
    m_PropertyInfoMap[leftTop.propertyName].setConnect();

    GY_PropertyInfo rightTop;
    rightTop.propertyName="RightTop";
    rightTop.propertyValue=QPointF(this->boundingRect().x()+this->boundingRect().width()
                                   ,this->boundingRect().y());
    rightTop.updateType = NotUpdate;
    rightTop.propertyType = PointPropertyType;
    rightTop.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateRightTop;
    m_PropertyInfoMap.insert(rightTop.propertyName,rightTop);
    m_PropertyInfoMap[rightTop.propertyName].setConnect();

    GY_PropertyInfo leftBottom;
    leftBottom.propertyName="LeftBottom";
    leftBottom.propertyValue=QPointF(this->boundingRect().x()
                                     ,this->boundingRect().y()+this->boundingRect().height());
    leftBottom.updateType = NotUpdate;
    leftBottom.propertyType = PointPropertyType;
    leftBottom.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateLeftBottom;
    m_PropertyInfoMap.insert(leftBottom.propertyName,leftBottom);
    m_PropertyInfoMap[leftBottom.propertyName].setConnect();

    GY_PropertyInfo rightBottom;
    rightBottom.propertyName="RightBottom";
    rightBottom.propertyValue=QPointF(this->boundingRect().x() + this->boundingRect().width()
                                  ,this->boundingRect().y() + this->boundingRect().height());
    rightBottom.updateType = NotUpdate;
    rightBottom.propertyType = PointPropertyType;
    rightBottom.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateRightBottom;
    m_PropertyInfoMap.insert(rightBottom.propertyName,rightBottom);
    m_PropertyInfoMap[rightBottom.propertyName].setConnect();

    GY_PropertyInfo rotationPoint;
    rotationPoint.propertyName="RotationPoint";
    rotationPoint.propertyValue=QPointF(this->boundingRect().x()+this->boundingRect().width()/2
                                        ,this->boundingRect().y()+this->boundingRect().height()/2);
    rotationPoint.updateType = NotUpdate;
    rotationPoint.propertyType = PointPropertyType;
    rotationPoint.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_TransformGroup::updateRotationPoint;
    m_PropertyInfoMap.insert(rotationPoint.propertyName,rotationPoint);
    m_PropertyInfoMap[rotationPoint.propertyName].setConnect();

}

bool GY_TransformGroup::updateIsVisible(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    this->setVisible(value.toBool());
    return true;
}

bool GY_TransformGroup::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    return true;
}

bool GY_TransformGroup::updateLeftTop(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF scaling = m_PropertyInfoMap["Scaling"].propertyValue.toPointF();
    QPointF point = this->mapFromScene(value.toPointF());
    point.setX(point.x()*scaling.x());
    point.setY(point.y()*scaling.y());
    m_PropertyInfoMap[name].propertyValue=point;
    QPointF rightTop= m_PropertyInfoMap["RightTop"].propertyValue.toPointF();
    QPointF leftBottom= m_PropertyInfoMap["LeftBottom"].propertyValue.toPointF();
    rightTop.setY(point.y());
    m_PropertyInfoMap["RightTop"].propertyValue = rightTop;
    leftBottom.setX(point.x());
    m_PropertyInfoMap["LeftBottom"].propertyValue = leftBottom;
    computationScaling();
//    this->setRotationCenter(m_PropertyInfoMap["RightBottom"].propertyValue.toPointF());
//    this->setTransformOriginPoint(QPointF(0,0));
    updateDraw();
    this->setEditPointF("LeftBottom",leftBottom);
    this->setEditPointF("RightTop",rightTop);
    this->setEditPointF(name,point);
//    QPointF scal = m_PropertyInfoMap["Scaling"].propertyValue.toPointF();
//    QPointF rbPoint = m_PropertyInfoMap["RightBottom"].propertyValue.toPointF();
//    qreal addX = -rbPoint.x()*scal.x()+rbPoint.x();
//    qreal addY = rbPoint.y()-rbPoint.y()*scal.y();
//    QPointF position = this->mapToScene(m_PropertyInfoMap["Position"].propertyValue.toPointF());
//    position.setX(position.x()+addX);
//    position.setY(position.y()+addY);
//    this->setPos(position);
//    m_PropertyInfoMap["Position"].propertyValue = this->mapFromScene(position);
    return true;
}

bool GY_TransformGroup::updateRightTop(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF scaling = m_PropertyInfoMap["Scaling"].propertyValue.toPointF();
    QPointF point = this->mapFromScene(value.toPointF());
    point.setX(point.x()*scaling.x());
    point.setY(point.y()*scaling.y());
    m_PropertyInfoMap[name].propertyValue=point;
    QPointF leftTop= m_PropertyInfoMap["LeftTop"].propertyValue.toPointF();
    QPointF rightBottom= m_PropertyInfoMap["RightBottom"].propertyValue.toPointF();
    leftTop.setY(point.y());
    m_PropertyInfoMap["LeftTop"].propertyValue = leftTop;
    rightBottom.setX(point.x());
    m_PropertyInfoMap["RightBottom"].propertyValue = rightBottom;
    computationScaling();
    updateDraw();
    this->setEditPointF("RightBottom",rightBottom);
    this->setEditPointF("LeftTop",leftTop);
    this->setEditPointF(name,point);
    return true;
}

bool GY_TransformGroup::updateLeftBottom(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF scaling = m_PropertyInfoMap["Scaling"].propertyValue.toPointF();
    QPointF point = this->mapFromScene(value.toPointF());
    point.setX(point.x()*scaling.x());
    point.setY(point.y()*scaling.y());
    m_PropertyInfoMap[name].propertyValue=point;
    QPointF leftTop= m_PropertyInfoMap["LeftTop"].propertyValue.toPointF();
    QPointF rightBottom= m_PropertyInfoMap["RightBottom"].propertyValue.toPointF();
    leftTop.setX(point.x());
    m_PropertyInfoMap["LeftTop"].propertyValue = leftTop;
    rightBottom.setY(point.y());
    m_PropertyInfoMap["RightBottom"].propertyValue = rightBottom;
    computationScaling();
    updateDraw();
    this->setEditPointF("RightBottom",rightBottom);
    this->setEditPointF("LeftTop",leftTop);
    this->setEditPointF(name,point);
    return true;
}

bool GY_TransformGroup::updateRightBottom(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF scaling = m_PropertyInfoMap["Scaling"].propertyValue.toPointF();
    QPointF point = this->mapFromScene(value.toPointF());
    point.setX(point.x()*scaling.x());
    point.setY(point.y()*scaling.y());
    m_PropertyInfoMap[name].propertyValue=point;
    QPointF rightTop= m_PropertyInfoMap["RightTop"].propertyValue.toPointF();
    QPointF leftBottom= m_PropertyInfoMap["LeftBottom"].propertyValue.toPointF();
    rightTop.setX(point.x());
    m_PropertyInfoMap["RightTop"].propertyValue = rightTop;
    leftBottom.setY(point.y());
    m_PropertyInfoMap["LeftBottom"].propertyValue = leftBottom;
    computationScaling();
    updateDraw();
    this->setEditPointF("LeftBottom",leftBottom);
    this->setEditPointF("RightTop",rightTop);
    this->setEditPointF(name,point);
    return true;
}

bool GY_TransformGroup::updateRotationPoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    return true;
}

bool GY_TransformGroup::updateRotation(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    qreal rotation = value.toReal();
    if(rotation>360) {
        rotation = fmod(rotation,360);
    }else if(rotation<-360) {
        rotation = fmod(rotation,-360);
    }
    m_PropertyInfoMap[name].propertyValue=rotation;
    updateDraw();
    return true;
}

bool GY_TransformGroup::updateScaling(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_TransformGroup::updateRotationInEditMode(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_TransformGroup::updateScaleInEditMode(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

void GY_TransformGroup::updateDraw()
{
    //围绕position旋转
    if(m_PropertyInfoMap["ScaleInEditMode"].propertyValue.toBool()) {
        this->setScaleX(m_PropertyInfoMap["Scaling"].propertyValue.toPointF().x());
        this->setScaleY(m_PropertyInfoMap["Scaling"].propertyValue.toPointF().y());
    }else {
        this->setScaleX(1);
        this->setScaleY(1);
    }
    if(m_PropertyInfoMap["RotationInEditMode"].propertyValue.toBool()) {
        this->setContainerRotation(m_PropertyInfoMap["Rotation"].propertyValue.toReal());
    }else {
        this->setContainerRotation(0);
    }
}

